package com.summer.socket.http;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;

/**
 * hello Netty Http响应的处理器
 */
public class HttpHandler extends SimpleChannelInboundHandler<HttpObject> {
    // SimpleChannelInboundHandler: 对于请求来讲相当于【入站/入境】这样的环节
    /*
    * 客户端每一次连接到我们的服务器都会有一个上下文对象 ChannelHandlerContext
    * 每一个 Channel 的生命周期：注册 -》
    *
    * */

    @Override
    public boolean acceptInboundMessage(Object msg) throws Exception {
        System.out.println("acceptInboundMessage... channel 允许入站msg");
        return super.acceptInboundMessage(msg);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("channelRead... channel 读取");
        super.channelRead(ctx, msg);
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelRegistered... channel 注册");
        super.channelRegistered(ctx);
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelUnregistered... channel 移除");
        super.channelUnregistered(ctx);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelActive... channel 活跃");
        super.channelActive(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelInactive... channel 不活跃（断开连接之后就不活跃了）");
        super.channelInactive(ctx);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelReadComplete... channel 读取完毕");
        super.channelReadComplete(ctx);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        System.out.println("userEventTriggered... 用户事件出发");
        super.userEventTriggered(ctx, evt);
    }

    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelWritabilityChanged... 可写更改");
        super.channelWritabilityChanged(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // 发生异常时应该关闭相应的channel 否则会积压变慢
        System.out.println("exceptionCaught... 发生异常统一处理");
        super.exceptionCaught(ctx, cause);
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        System.out.println("handlerAdded... 通道处理器类添加");
        super.handlerAdded(ctx);
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        System.out.println("handlerRemoved... 通道处理器类移除");
        super.handlerRemoved(ctx);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
        if(!(msg instanceof HttpRequest))
            return;
//        if (((HttpRequest)msg).uri().indexOf("favicon") != -1)
//            return;

        // 通过上下文获取 channel
        Channel channel = ctx.channel();
        // 打印客户端地址
        System.out.println(channel.remoteAddress());
        // 发送消息
        // socket 的数据交互都是通过一个缓冲区进行的，copiedBuffer 就是将 String 以指定格式复制到一个 buf 里
        ByteBuf content = Unpooled.copiedBuffer("Hello netty~~", CharsetUtil.UTF_8);

        // 构建一个 HttpResponse，第一个参数是http协议版本，第二个参数是http响应的状态码（404或200等），第三个就是内容
        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
//        response.headers().set()
        response.headers().add(HttpHeaderNames.CONTENT_TYPE, "text/plain");
        response.headers().add(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());

        // 把响应刷到客户端
        ctx.writeAndFlush(response);
    }
}
